home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 49 / Amiga Format CD49 (2000-01-17)(Future Publishing)(GB)(Track 1 of 3)[!][issue 2000-02].iso / -serious- / programming / mui / mcc_popph / mcc_popph_src / mccheader.c < prev    next >
C/C++ Source or Header  |  1999-11-30  |  18KB  |  593 lines

  1.  
  2. // 17:45:13, 20 Maj 1999
  3. //  add #define MCC_USES_IFFPARSE to autoinit iffparse.library
  4.  
  5. // 22:59:21, 17 Grudzieï 1998
  6. //  add #define MCC_USES_LOCALE to autoinit locale.library
  7.  
  8. /// README
  9. /*****************************************************************************
  10.  
  11. This code serves as a basis for writing a library-based MUI custom class
  12. (xyz.mcc) and its preferences editor (xyz.mcp).
  13.  
  14. You need to define a few things in your main source file, then include
  15. this file and then continue with your classes methods. The order is
  16. important, mccheader.c must be the first code-generating module.
  17.  
  18. Things to be defined before mccheader.c is included:
  19.  
  20. (1)  UserLibID     - version string for your class. must follow normal $VER: string conventions.
  21. (2)  VERSION       - version number of the class. must match the one given in the $VER: string.
  22. (3)  REVISION      - revision number of the class. must match the one given in the $VER: string.
  23. (4)  CLASS         - Name of your class, ".mcc" or ".mcp" must always be appended.
  24.  
  25. (5)  SUPERCLASS    - superclass of your class.
  26. (6)  struct Data   - instance data structure.
  27. (7)  _Dispatcher   - your dispatcher function.
  28.  
  29. (8)  SUPERCLASSP   - Superclass of the preferences class, must be MUIC_Mccprefs or a subclass.
  30. (9)  struct DataP  - instance data structure of preferences class.
  31. (10) _DispatcherP  - dispatcher for the preferences class.
  32.  
  33. Items (1) to (4) must always be defined. If you create a stand-alone
  34. custom class (*.mcc) without preferences editor, also define (5), (6)
  35. and (7). Name your class and the resulting ouptut file "Myclass.mcc".
  36.  
  37. If you create a preferences class (*.mcp) for a custom class, define
  38. (8), (9) and (10) instead of (5), (6) and (7). Name your class and the
  39. resulting output file "Myclass.mcp".
  40.  
  41. If you create a custom class with included preferences editor, define
  42. all the above. Note that in this case, the name of your class and the
  43. resulting output file is always "Myclass.mcc". MUI will automatically
  44. recognize that there's also a "Myclass.mcp" included. Having a builtin
  45. preferences class reduces the need for a second file but increases the
  46. size and memory consuption of the class.
  47.  
  48. If your class needs custom initialization (e.g. opening other
  49. libraries), you can define
  50.         ClassInit
  51.         ClassExit
  52. to point to custom functions. These functions need to have the prototypes
  53.         BOOL ClassInitFunc(struct Library *base);
  54.         VOID ClassExitFunc(struct Library *base);
  55. and will be called right after the class has been created and right
  56. before the class is being deleted. If your init func returns FALSE,
  57. the custom class will be unloaded immediately.
  58.  
  59. Define the minimum version of muimaster.libray in MASTERVERSION. If you
  60. don't define MASTERVERSION, it will default to MUIMASTER_VMIN from the
  61. mui.h include file.
  62.  
  63. This code automatically defines and initializes the following variables:
  64.         struct Library *MUIMasterBase;
  65.         struct Library *SysBase;
  66.         struct Library *UtilityBase;
  67.         struct Library *DOSBase;
  68.         struct Library *GfxBase;
  69.         struct Library *IntuitionBase;
  70.         struct Library *MUIClassBase;       /* your classes library base */
  71.         struct MUI_CustomClass *ThisClass;  /* your custom class */
  72.         struct MUI_CustomClass *ThisClassP; /* your preferences class */
  73.  
  74. Example: Myclass.c
  75.         #define CLASS      MUIC_Myclass // name of class, e.g. "Myclass.mcc"
  76.         #define SUPERCLASS MUIC_Area    // name of superclass
  77.         struct Data
  78.         {
  79.                 LONG          MyData;
  80.                 struct Foobar MyData2;
  81.                 // ...
  82.         };
  83.         #define UserLibID "$VER: Myclass.mcc 17.53 (11.11.96)"
  84.         #define VERSION   17
  85.         #define REVISION  53
  86.         #include "mccheader.c"
  87.         ULONG ASM SAVEDS _Dispatcher(REG(a0) struct IClass *cl,
  88.                                          REG(a2) Object *obj,
  89.                                          REG(a1) Msg msg)
  90.         {
  91.                 // ...
  92.         }
  93.  
  94. Compiling and linking with SAS-C can look like this:
  95.         Myclass.mcc: Myclass.c
  96.                 sc $(CFLAGS) $*.c OBJNAME $*.o
  97.                 slink to $@ from $*.o lib $(LINKERLIBS) $(LINKERFLAGS)
  98.  
  99. Note well that we don't use SAS library creation feature here, it simply
  100. sucks too much. It's not much more complicated to do the library
  101. initialziation ourselves and we have better control over everything.
  102.  
  103. Make sure to read the whole source to get some interesting comments
  104. and some understanding on how libraries are created!
  105.  
  106. *****************************************************************************/
  107. //|
  108.  
  109. /// Includes
  110.  
  111. #include <exec/types.h>
  112. #include <exec/memory.h>
  113. #include <exec/libraries.h>
  114. #include <exec/semaphores.h>
  115. #include <exec/resident.h>
  116. #include <exec/execbase.h>
  117. #include <dos/dos.h>
  118. #include <clib/exec_protos.h>
  119. #include <pragmas/exec_sysbase_pragmas.h>
  120.  
  121. #ifdef MCC_USES_ASL
  122. #include <clib/asl_protos.h>
  123. #endif
  124.  
  125. #ifdef MCC_USES_LOCALE
  126. #include <clib/locale_protos.h>
  127. #endif
  128.  
  129.  
  130. #include "debug.h"
  131.  
  132. //|
  133.  
  134. /* The name of the class will also become the name of the library. */
  135. /* We need a pointer to this string in our ROMTag (see below). */
  136.  
  137. static const char UserLibName[] = CLASS;
  138.  
  139. /// Global Data
  140. /* Here's our global data, described above. */
  141.  
  142. struct Library *MUIClassBase;
  143. struct Library *MUIMasterBase;
  144. extern struct Library *SysBase;
  145. struct Library *UtilityBase;
  146. struct Library *DOSBase;
  147. struct GfxBase *GfxBase;
  148. struct Library *IntuitionBase;
  149.  
  150. #ifdef MCC_USES_LOCALE
  151. struct Library *LocaleBase;
  152. struct Locale  *Locale;
  153. #endif
  154.  
  155. #ifdef MCC_USES_IFFPARSE
  156. struct Library *IFFParseBase;
  157. #endif
  158.  
  159. #ifdef MCC_USES_DATATYPES
  160. struct Library *DataTypesBase;
  161. #endif
  162.  
  163. #ifdef MCC_USES_ASL
  164. struct Library *AslBase;
  165. #endif
  166.  
  167. //|
  168. /// Few #defines etc
  169. #ifdef SUPERCLASS
  170. struct MUI_CustomClass *ThisClass;
  171. #endif
  172.  
  173. #ifdef SUPERCLASSP
  174. struct MUI_CustomClass *ThisClassP;
  175. #endif
  176.  
  177. #ifdef _DCC
  178. #define REG(x) __ ## x
  179. #define ASM
  180. #define SAVEDS __geta4
  181. #else
  182. #define REG(x) register __ ## x
  183. #define ASM    __asm
  184. #define SAVEDS __saveds
  185. #endif
  186. //|
  187. /// Library Header
  188. /* Our library structure, consisting of a struct Library, a segment pointer */
  189. /* and a semaphore. We need the semaphore to protect init/exit stuff in our */
  190. /* open/close functions */
  191.  
  192. struct LibraryHeader
  193. {
  194.         struct Library         lh_Library;
  195.         BPTR                   lh_Segment;
  196.         struct SignalSemaphore lh_Semaphore;
  197. };
  198. //|
  199.  
  200. /// Prototypes for all library functions
  201.  
  202. struct LibraryHeader * ASM LibInit   (REG(a0) BPTR Segment);
  203. BPTR                   ASM LibExpunge(REG(a6) struct LibraryHeader *base);
  204. struct LibraryHeader * ASM LibOpen   (REG(a6) struct LibraryHeader *base);
  205. BPTR                   ASM LibClose  (REG(a6) struct LibraryHeader *base);
  206. LONG                   ASM LibNull   (VOID);
  207. ULONG           SAVEDS ASM MCC_Query (REG(d0) LONG which);
  208. //|
  209. /// Prototypes for a few sub-functions
  210.  
  211. BOOL ASM UserLibInit   (REG(a6) struct Library *base);
  212. BOOL ASM UserLibExpunge(REG(a6) struct Library *base);
  213. BOOL ASM UserLibOpen   (REG(a6) struct Library *base);
  214. BOOL ASM UserLibClose  (REG(a6) struct Library *base);
  215. //|
  216. /// This is the librarie's jump table
  217. static const APTR LibVectors[] =
  218. {
  219.         LibOpen,
  220.         LibClose,
  221.         LibExpunge,
  222.         LibNull,
  223.         MCC_Query,
  224.         (APTR)-1
  225. };
  226. //|
  227. /// Dummy entry point and LibNull() function all in one
  228.  
  229. LONG ASM LibNull(VOID)
  230. {
  231.         return(NULL);
  232. }
  233. //|
  234. /// Here's what makes us a library
  235.  
  236. static const struct Resident ROMTag =
  237. {
  238.         RTC_MATCHWORD,
  239.         &ROMTag,
  240.         &ROMTag + 1,
  241.         0,
  242.         VERSION,
  243.         NT_LIBRARY,
  244.         0,
  245.         UserLibName,
  246.         UserLibID,
  247.         LibInit
  248. };
  249. //|
  250.  
  251. /******************************************************************************/
  252. /* Standard Library Functions, all of them are called in Forbid() state.      */
  253. /******************************************************************************/
  254.  
  255. /// LibInit
  256. struct LibraryHeader * ASM SAVEDS LibInit(REG(a0) BPTR Segment)
  257. {
  258. struct LibraryHeader *base;
  259.  
  260.         D(bug(__NAME ": LibInit\n"));
  261.  
  262.         SysBase = *((struct Library **)4);
  263.  
  264.                 #ifdef _M68040
  265.                 if (!(((struct ExecBase *)SysBase)->AttnFlags & AFF_68040)) return(NULL);
  266.                 #endif
  267.                 #ifdef _M68030
  268.                 if (!(((struct ExecBase *)SysBase)->AttnFlags & AFF_68030)) return(NULL);
  269.                 #endif
  270.                 #ifdef _M68020
  271.                 if (!(((struct ExecBase *)SysBase)->AttnFlags & AFF_68020)) return(NULL);
  272.                 #endif
  273.  
  274.         if (base = (struct LibraryHeader *)MakeLibrary((APTR)LibVectors,NULL,NULL,sizeof(struct LibraryHeader),NULL))
  275.                 {
  276.                 base->lh_Library.lib_Node.ln_Type = NT_LIBRARY;
  277.                 base->lh_Library.lib_Node.ln_Name = (char *)UserLibName;
  278.                 base->lh_Library.lib_Flags        = LIBF_CHANGED | LIBF_SUMUSED;
  279.                 base->lh_Library.lib_Version      = VERSION;
  280.                 base->lh_Library.lib_Revision     = REVISION;
  281.                 base->lh_Library.lib_IdString     = (char *)UserLibID;
  282.  
  283.                 base->lh_Segment  = Segment;
  284.  
  285.                 InitSemaphore(&base->lh_Semaphore);
  286.  
  287.                 AddLibrary((struct Library *)base);
  288.                 }
  289.         else
  290.                 {
  291. //   D(DBF_LIB,bug("\7MakeLibrary() failed\n"));
  292.                 }
  293.  
  294.         return(base);
  295. }
  296. //|
  297. /// LibExpunge
  298.  
  299. BPTR ASM SAVEDS LibExpunge(REG(a6) struct LibraryHeader *base)
  300. {
  301. struct Library *SysBase = *((struct Library **)4);
  302. BPTR rc;
  303.  
  304.         D(bug(__NAME ": Expunge: OpenCount = %ld\n",base->lh_Library.lib_OpenCnt));
  305.  
  306.         if (base->lh_Library.lib_OpenCnt)
  307.         {
  308.                 base->lh_Library.lib_Flags |= LIBF_DELEXP;
  309.                 D(bug(__NAME ": Setting LIBF_DELEXP\n"));
  310.                 return(NULL);
  311.         }
  312.  
  313.         Remove((struct Node *)base);
  314.         rc = base->lh_Segment;
  315.         FreeMem((BYTE *)base - base->lh_Library.lib_NegSize,base->lh_Library.lib_NegSize + base->lh_Library.lib_PosSize);
  316.  
  317.         return(rc);
  318. }
  319. //|
  320. /// LibOpen
  321. struct LibraryHeader * ASM SAVEDS LibOpen(REG(a6) struct LibraryHeader *base)
  322. {
  323. struct Library *SysBase = *((struct Library **)4);
  324. struct LibraryHeader *rc;
  325.  
  326.         base->lh_Library.lib_OpenCnt++;
  327.         base->lh_Library.lib_Flags &= ~LIBF_DELEXP;
  328.  
  329.         D(bug(__NAME ": LibOpen (OC = %ld)\n", base->lh_Library.lib_OpenCnt));
  330.  
  331.         ObtainSemaphore(&base->lh_Semaphore);
  332.  
  333.         if (UserLibOpen((struct Library *)base))
  334.         {
  335.                 rc = base;
  336.         }
  337.         else
  338.         {
  339.                 rc = NULL;
  340.                 base->lh_Library.lib_OpenCnt--;
  341.                 D(bug(__NAME ": \7UserLibOpen() failed\n"));
  342.         }
  343.  
  344.         ReleaseSemaphore(&base->lh_Semaphore);
  345.  
  346.         return(rc);
  347. }
  348. //|
  349. /// LibClose
  350.  
  351. BPTR ASM SAVEDS LibClose(REG(a6) struct LibraryHeader *base)
  352. {
  353.         struct Library *SysBase = *((struct Library **)4);
  354.         BPTR rc = NULL;
  355.  
  356.         D(bug(__NAME ": LibClose (OC = %ld) %s\n", base->lh_Library.lib_OpenCnt,base->lh_Library.lib_OpenCnt==0 ? "\7ERROR" : ""));
  357.  
  358.         ObtainSemaphore(&base->lh_Semaphore);
  359.         UserLibClose((struct Library *)base);
  360.         ReleaseSemaphore(&base->lh_Semaphore);
  361.  
  362.         if (--base->lh_Library.lib_OpenCnt == 0)
  363.                 {
  364.                 if (base->lh_Library.lib_Flags & LIBF_DELEXP)
  365.                         {
  366.                         rc = LibExpunge(base);
  367.                         }
  368.                 }
  369.  
  370.         return(rc);
  371. }
  372. //|
  373.  
  374. /// UserLibOpen
  375.  
  376. BOOL ASM SAVEDS UserLibOpen(REG(a6) struct Library *base)
  377. {
  378.         ULONG ASM _Dispatcher(REG(a0) struct IClass *cl, REG(a2) Object *obj, REG(a1) Msg msg);
  379.         ULONG ASM _DispatcherP(REG(a0) struct IClass *cl, REG(a2) Object *obj, REG(a1) Msg msg);
  380.         BOOL ClassInitFunc(struct Library *base);
  381.  
  382.         D(bug(__NAME ": UserLibOpen (OC: %ld)\n",base->lib_OpenCnt));
  383.  
  384.         if (base->lib_OpenCnt!=1)
  385.                 return(TRUE);
  386.  
  387.         #ifndef MASTERVERSION
  388.         #define MASTERVERSION MUIMASTER_VMIN
  389.         #endif
  390.  
  391.         if (MUIMasterBase = OpenLibrary("muimaster.library",MASTERVERSION))
  392.         {
  393.                 #ifdef SUPERCLASS
  394.                 if (ThisClass = MUI_CreateCustomClass(base,SUPERCLASS,NULL,sizeof(struct Data),_Dispatcher))
  395.                 #endif
  396.                 {
  397.                         #ifdef SUPERCLASSP
  398.                         if (ThisClassP = MUI_CreateCustomClass(base,SUPERCLASSP,NULL,sizeof(struct DataP),_DispatcherP))
  399.                         #endif
  400.                         {
  401.                                 #ifdef SUPERCLASS
  402.                                 #define THISCLASS ThisClass
  403.                                 #else
  404.                                 #define THISCLASS ThisClassP
  405.                                 #endif
  406.  
  407.                                 UtilityBase   = THISCLASS->mcc_UtilityBase;
  408.                                 DOSBase       = (struct DosLibrary *)THISCLASS->mcc_DOSBase;
  409.                                 GfxBase       = (struct GfxBase *)THISCLASS->mcc_GfxBase;
  410.                                 IntuitionBase = THISCLASS->mcc_IntuitionBase;
  411.  
  412.                                 #ifdef MCC_USES_DATATYPES
  413.                                 if(!(DataTypesBase = OpenLibrary("datatypes.library", 38)))
  414.                                         return(FALSE);
  415.                                 #endif
  416.  
  417.                                 #ifdef MCC_USES_LOCALE
  418.                                 if(((LocaleBase = OpenLibrary("locale.library", 38)) == NULL))
  419.                                        return(FALSE);
  420.                                 Locale  = OpenLocale(NULL);
  421.                                 #endif               
  422.  
  423.                                 #ifdef MCC_USES_IFFPARSE
  424.                                 if(((IFFParseBase = OpenLibrary("iffparse.library", 37)) == NULL))
  425.                                        return(FALSE);
  426.                                 #endif
  427.  
  428.                                 #ifdef MCC_USES_ASL
  429.                                 if((( AslBase = OpenLibrary("asl.library", 37) ) == NULL))
  430.                                        return(FALSE);
  431.                                 #endif
  432.  
  433.  
  434.                                 #ifndef ClassInit
  435.                                 return(TRUE);
  436.                                 #else
  437.                                 if (ClassInitFunc(base))
  438.                                 {
  439.                                         return(TRUE);
  440.                                 }
  441.  
  442.                                 #ifdef SUPERCLASSP
  443.                                 MUI_DeleteCustomClass(ThisClassP);
  444.                                 ThisClassP = NULL;
  445.                                 #endif
  446.  
  447.                                 #endif
  448.                         }
  449.                         #ifdef SUPERCLASSP
  450.                         #ifdef SUPERCLASS
  451.                         MUI_DeleteCustomClass(ThisClass);
  452.                         ThisClass = NULL;
  453.                         #endif
  454.                         #endif
  455.                 }
  456.                 CloseLibrary(MUIMasterBase);
  457.                 MUIMasterBase = NULL;
  458.         }
  459.         D(bug(__NAME ": muimaster fail.: %08lx %s\n", base, base->lib_Node.ln_Name));
  460.  
  461.         return(FALSE);
  462. }
  463. //|
  464. /// UserLibClose
  465. BOOL ASM SAVEDS UserLibClose(REG(a6) struct Library *base)
  466. {
  467. void ClassExitFunc(struct Library *base);
  468.  
  469.         D(bug(__NAME ": UserLibClose (OC = %ld)\n", base->lib_OpenCnt));
  470.  
  471.         if (base->lib_OpenCnt==1)
  472.         {
  473.                 #ifdef ClassExit
  474.                 ClassExitFunc(base);
  475.                 #endif
  476.  
  477.                 #ifdef SUPERCLASSP
  478.                 if (ThisClassP)
  479.                 {
  480.                         MUI_DeleteCustomClass(ThisClassP);
  481.                         ThisClassP = NULL;
  482.                 }
  483.                 #endif
  484.  
  485.                 #ifdef SUPERCLASS
  486.                 if (ThisClass)
  487.                 {
  488.                         MUI_DeleteCustomClass(ThisClass);
  489.                         ThisClass = NULL;
  490.                 }
  491.                 #endif
  492.  
  493.                 #ifdef MCC_USES_IFFPARSE
  494.                 if(IFFParseBase)
  495.                    {
  496.                    CloseLibrary(IFFParseBase);
  497.                    }
  498.                 #endif
  499.  
  500.                 #ifdef MCC_USES_LOCALE
  501.                 if(LocaleBase)
  502.                    {
  503.                    if(Locale)
  504.                        CloseLocale(Locale);
  505.  
  506.                    CloseLibrary(LocaleBase);
  507.                    }
  508.                 #endif 
  509.  
  510.                 #ifdef MCC_USES_DATATYPES
  511.                 if (DataTypesBase)
  512.                         {
  513.                         CloseLibrary(DataTypesBase);
  514.                         DataTypesBase = NULL;
  515.                         }
  516.                 #endif
  517.  
  518.                 #ifdef MCC_USES_ASL
  519.                 if( AslBase )
  520.                    {
  521.                    CloseLibrary( AslBase );
  522.                    AslBase = NULL;
  523.                    }
  524.                 #endif
  525.  
  526.  
  527.                 if (MUIMasterBase)
  528.                 {
  529.                         CloseLibrary(MUIMasterBase);
  530.                         MUIMasterBase = NULL;
  531.                 }
  532.  
  533.         }
  534.  
  535.         return(TRUE);
  536. }
  537. //|
  538. /// MCC_Query
  539. ULONG SAVEDS ASM MCC_Query(REG(d0) LONG which)
  540. {
  541.         switch (which)
  542.         {
  543.                 #ifdef SUPERCLASS
  544.                 case 0: return((ULONG)ThisClass);
  545.                 #endif
  546.  
  547.                 #ifdef SUPERCLASSP
  548.                 case 1: return((ULONG)ThisClassP);
  549.                 #endif
  550.  
  551.                 #ifdef PREFSIMAGEOBJECT
  552.                 case 2:
  553.                 {
  554.                         Object *obj = PREFSIMAGEOBJECT;
  555.                         return((ULONG)obj);
  556.                 }
  557.                 #endif
  558.  
  559.                 #ifdef ONLYGLOBAL
  560.                 case 3:
  561.                 {
  562.                         return(TRUE);
  563.                 }
  564.                 #endif
  565.         }
  566.         return(NULL);
  567. }
  568. //|
  569.  
  570. /// DoSuperNew()
  571.  
  572. ULONG __stdargs DoSuperNew(struct IClass *cl, Object *obj, ULONG tag1, ...)
  573. {
  574.     return(DoSuperMethod(cl, obj, OM_NEW, &tag1, NULL));
  575. }
  576. //|
  577.  
  578. /*
  579. /// main()
  580. long main()
  581. {
  582. BPTR  Handle;
  583. char  Warning[] = "This custom class is for use with MUI 3.5+ only\n";
  584.  
  585.         if(Handle = Output())
  586.                 {
  587.                 Write(Handle, Warning, strlen(Warning));
  588.                 }
  589.         return(20);
  590. }
  591. //|
  592. */
  593.